export function isObject(obj) {
  return obj !== null && typeof obj === "object" && !Array.isArray(obj);
};

export function isNull(value) {
  return value === null;
};

// 判断是否是基础类型
export function inPrimitive(type) {
  return ['string', 'number', 'bigint', 'boolean', 'null', 'undefined', 'symbol'].includes(type);
}

export function getVal(obj, expr) {
  if(!expr){
    return obj;
  }
  return expr.split('.').reduce((acc, cur) => acc && acc[cur], obj);
}

export function hasOwnPro(obj, property) {
  return isObject(obj) ? obj.hasOwnProperty(property) : false;
}

export function kebabCase(str) {
  return str.replace(/[A-Z]/g, (x) => '-'+x.toLowerCase())
}

/**
 * {
 *    onSelectChange: () => {},
 *    onClick: () => {}
 * }
 * ==>
 * {
 *  select-change: () => 
 *  click: () =>
 * }
 */
export function eventsKebabCase(obj) {
  if (!isObject(obj)) return obj;
  return Object.keys(obj).reduce((events, key) => {
    let eventName = key.replace(/^on/, '');
    eventName = eventName.charAt(0)
    .toLowerCase()+eventName.substring(1)
    .replace(/[A-Z]/g, (x) => '-'+x.toLowerCase())
    events[eventName] = obj[key];
    return events;
  }, {})
}

// 获取指定的键
export function pick(target, keys) {
  if (!keys) return target;
  return Object.keys(target).reduce((newData, key) => {
    const flag = typeof keys === "function" ? keys(key) : keys.includes(key);
    flag && (newData[key] = target[key]);
    return newData;
  }, {});
}

// 排除指定键
export function omit(target, keys) {
  if (!keys) return target;
  return Object.keys(target).reduce((newData, key) => {
    const flag = typeof keys === "function" ? keys(key) : keys.includes(key);
    !flag && (newData[key] = target[key]);
    return newData;
  }, {});
}

//深拷贝
export function merge(target, ...sources) {
  for (const source of sources) {
    for (const [key, value] of Object.entries(source)) {
      if (isObject(value)) {
        const targetValue = target[key];
        const newTarget = isObject(targetValue)
          ? targetValue
          : Array.isArray(value) ? [] : {};
        target[key] = merge(newTarget, value);
      } else {
        target[key] = value;
      }
    }
  }
  return target;
}

// 扁平化
export function flatObj(data) {
  let target = {}
  let setItem = function(data,name) {
      const keys = Object.keys(data);
      keys.forEach(function(key,i){
          //将key值存储到target对象中
          let value = data[key];
          if(typeof value === 'object' && value !== null){
              key = !name && key || name+'['+key+']';
              setItem(value,key);
          }else{
              key = !name && key || name+'['+key+']';
              target[key] = value
          }
      });
      // 避免空值，导致属性丢失
      if(name && keys.length == 0) {
          target[name] = data;
      }
  };
  setItem(data);
  return target;
}

export function isExpr(str) {
  return /^{\s*{\s*([^}]+?)\s*}\s*}$/.test(str);
}

export const exprRegex = new RegExp("{{\\s*([^}]+?)\\s*}}");

// 解析器s
export function parser(expr, context) {
  console.log('hidden', expr, context)
  return compiler(expr)(context);
}
/**
 * 编译器
 * exprOrFn = "{{ formData.name }}";
 * exprOrFn = " 1> 3"
 * exprOrFn = true;
 */
export function compiler(exprOrFn) {
  // 在字符串中\本身就是一个转义字符，所以需要\\来表示\
  let exprReg = new RegExp("{{\\s*([^}]+?)\\s*}}");
  exprReg.test(exprOrFn) && (exprOrFn = exprReg.exec(exprOrFn)[1]);
  const fn = new Function('args', `with(this) {
    if(typeof ${exprOrFn} === 'function') {
      return (${exprOrFn}).apply(this, params);
    }
    return ${exprOrFn};
  }`)
  return function(context, ...args) {
    return fn.call(context || this, args);
  }
}